package com.yeqing.netty;

import com.yeqing.util.ByteBufferUtil;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

public class NettyBase {

    /**
     * 转换字符串和ByteBuffer
     */
    public static void translate() {
        String str1 = "helloNetty";
        String str2;
        String str3;

        // 把str1通过utf8编码成buffer
        ByteBuffer buffer = StandardCharsets.UTF_8.encode(str1);
        ByteBuffer wrap = ByteBuffer.wrap(str1.getBytes());

        ByteBufferUtil.debugAll(buffer);
        ByteBufferUtil.debugAll(wrap);

        str2 = StandardCharsets.UTF_8.decode(buffer).toString();
        System.out.println(str2);

        str3 = StandardCharsets.UTF_8.decode(wrap).toString();
        System.out.println(str3);

    }

    public static void zhanBaoAndBanBao() {
        ByteBuffer buffer = ByteBuffer.allocate(32);
        // 模拟粘包和半包
        buffer.put("Hello,world\nI'm Jack\nHo".getBytes(StandardCharsets.UTF_8));
        split(buffer);
        buffer.put("w are you\n".getBytes(StandardCharsets.UTF_8));
        split(buffer);
    }

    /**
     * 解决粘包和半包
     */
    public static void split(ByteBuffer buffer) {
        // 切换读模式
        buffer.flip();
        for (int i = 0; i < buffer.limit(); i++) {
            // 找到完整消息
            if (buffer.get(i) == '\n') {
                // 获取相对于上一个\n的位置
                int length = i + 1 - buffer.position();
                // 给单独的信息创建适合长度
                final ByteBuffer target = ByteBuffer.allocate(length);
                // 从buffer中读取，依次写入target
                for (int j = 0; j < length; j++) {
                    target.put(buffer.get());
                }
                // 打印查看结果
                ByteBufferUtil.debugAll(target);
            }
        }
        // 清空已读部分，把未读的向前移动，并切换写模式
        buffer.compact();
    }


    public static void zhanBaoAndBanBao2() {
        ByteBuffer buffer = ByteBuffer.allocate(32);
        // 模拟粘包和半包
        buffer.put("Hello,world\nI'm Jack\nHo".getBytes(StandardCharsets.UTF_8));
        split2(buffer);
        buffer.put("w are you\n".getBytes(StandardCharsets.UTF_8));
        split2(buffer);
    }

    public static void split2(ByteBuffer buffer) {
        // 1. 通过get(i)遍历ByteBuffer，当遇到\n后进行处理
        // 2. 记录从position到index的数据长度，申请对应大小的缓冲区
        // 3. 将缓冲区中的内容写到新的buffer中
        // 4. 调用compact()，把未处理的数据往前移动
        // 切换到读模式，把position设置为0
        buffer.flip();
        int length = buffer.limit();
        for (int i = 0; i < length; i++) {
            // 找到\n的下标
            if (buffer.get(i) == '\n') {
                int len = i + 1 - buffer.position();
                ByteBuffer target = ByteBuffer.allocate(len);
                for (int j = 0; j < len; j++) {
                    target.put(buffer.get());
                }
                // 遍历完打印内容
                ByteBufferUtil.debugAll(target);
            }
        }
        // 遍历完可能最后不是\n结尾，需要把没处理的数据往前放
        buffer.compact();
    }


    public static void useFileChannelWriteTxt() throws Exception {
        try (
                FileChannel channel = new FileOutputStream("/Users/cyq/Develop/三国/张飞23.txt").getChannel();
        ) {
            String msg = "hel2lo world32322";
            ByteBuffer buffer = ByteBuffer.allocate(msg.length());
            buffer.put(msg.getBytes(StandardCharsets.UTF_8));
            buffer.flip();
            channel.write(buffer);
        }
    }

    /**
     * 读文件
     * @throws Exception
     */
    public static void useFileChannelReadTxt() throws Exception {
        try (
            FileChannel channel = new FileInputStream("/Users/cyq/Develop/三国/张飞23.txt").getChannel();
        ) {
            ByteBuffer buffer = ByteBuffer.allocate(32);
            channel.read(buffer);
            buffer.flip();
            System.out.println(StandardCharsets.UTF_8.decode(buffer));
            buffer.clear();
        }
    }

    public static void useFileChannelTransmission() throws Exception {
        try (
                FileChannel from = new FileInputStream("/Users/cyq/Develop/三国/张飞23.txt").getChannel();
                FileChannel to = new FileOutputStream("/Users/cyq/Develop/三国/张飞233.txt").getChannel();
        ) {
            from.transferTo(0, from.size(), to);
        }
    }

    public static void main(String[] args) throws Exception {
//        translate();

//        zhanBaoAndBanBao();
//        zhanBaoAndBanBao2();

//        useFileChannelWriteTxt();
        useFileChannelReadTxt();

//        useFileChannelTransmission();
    }
}